/**
 * 
 */
package spatial.geometry;

import java.awt.geom.*;

/**
 * A circle is defined with a center point (location) and a radius.
 * 
 * This implementation is a wrap of java.awt.geom.Ellipse2D.Double. Note that
 * the direction of the Y axis used in java.awt.geom.Ellipse2D.Double is
 * opposite to the one we use in daily life. Therefore
 * java.awt.geom.Ellipse2D.Double's upper-left corner is in fact the lower-left
 * corner.
 * 
 * @author wu wei
 * 
 */
public class Circle implements BasicShape {

	protected Location center;

	protected double radius;

	protected Ellipse2D.Double ellipse;

	public Circle(Location center, double r) {
		this.center = center;
		this.radius = r;
		this.buildEllipse();
	}

	private void buildEllipse() {
		/**
		 * <pre>
		 * x = center.x - radius
		 * y = center.y - radius
		 * width = 2 * radius
		 * height = 2* radius
		 * build ellipse with the above as parameters
		 * </pre>
		 */

		double x = this.center.getX() - radius;
		double y = this.center.getY() - radius;
		double width = 2 * radius;
		double height = width;
		this.ellipse = new Ellipse2D.Double(x, y, width, height);
	}

	/**
	 * Move this shape such that the given location is its center.
	 * 
	 * @param loc
	 */
	public void centerTo(Location loc) {
		/**
		 * <pre>
		 * set center to new center 
		 * re-build ellipse
		 * </pre>
		 */
		if (this.center != loc) {
			this.center = loc;
			this.buildEllipse();
		}
	}

	public boolean contains(Location l) {
		return (this.center.distance(l) < this.radius);
		// return this.ellipse.contains(l.getX(), l.getY());
	}

	public boolean contains(Rectangle rec) {
		return this.ellipse.contains(rec);
	}

	public Rectangle getRectBounds() {
		return new Rectangle(new Location(this.ellipse.getX(), this.ellipse
				.getY()), this.ellipse.getWidth(), this.ellipse.getHeight());
	}

	public boolean intersects(Rectangle rec) {
		return this.ellipse.intersects(rec);
	}

	public boolean intersects(Circle c) {
		/**
		 * <pre>
		 * get distance between the two circles' centers
		 * if distance &lt; sum of radius
		 * 	return true
		 * else
		 * 	return false
		 * end if
		 * </pre>
		 */
		double distance = this.center.distance(c.center);
		if (distance < (this.radius + c.radius)) {
			return true;
		}
		return false;
	}

	public Location getCenter() {
		return center;
	}

	public double getRadius() {
		return radius;
	}

	public Circle clone() {
		return new Circle(this.center, this.radius);
	}

	@Override
	public String toString() {
		String s = "(center=" + this.center.toString() + ", radius="
				+ this.radius + ")";
		return s;
	}

	public BasicShape deepClone() {
		return new Circle(this.center, this.radius);
	}

}
